/**
 * 
 */
package org.youisoft.summer.evaluator.registry;

import java.util.Iterator;
import java.util.ServiceLoader;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.youisoft.summer.evaluator.function.Function;
import org.youisoft.summer.evaluator.function.core.AdapterFunction;

/**
 * @author zijiang.jl
 *
 */
public class DefaultFunctionRegistry extends AbstractRegistry implements FunctionRegistry{
	private Log logger=LogFactory.getLog(FunctionRegistry.class);
	private static final java.util.Map<String, Function> baseMaps;
	private static final java.util.Map<String, Function> customFuns;
	private static final java.util.Map<String, String> aliasMaps;
	static {
		baseMaps=new java.util.HashMap<String, Function>();
		customFuns=new java.util.concurrent.ConcurrentHashMap<String, Function>();
		aliasMaps=new java.util.concurrent.ConcurrentHashMap<String, String>();
		ServiceLoader<Function> sl=java.util.ServiceLoader.load(Function.class);
		Iterator<Function> it=sl.iterator();
		while(it.hasNext()){
			Function f=it.next();
			f.init();
			baseMaps.put(f.getName(), f);
		}	
	}
	
	@Override
	public void registerAlias(String name, String... alias) {
		if(alias!=null){
			if(this.findFunction(name)!=null){
				for(String a:alias){
					if(a!=null) aliasMaps.put(a, name);
				}
			}else{
				super.registerAlias(name, alias);
			}
		}
	
	}


	@java.lang.Override
	public void register(Function function){
		if(this.findFunction(function.getName())!=null){
			logger.warn(function.getName()+" already exist");
		}
		if(function.isValidate()) {
			customFuns.put(function.getName(), function);
			this.registerAlias(function.getName(), function.getAlias());
		}
	}
	


	@java.lang.Override
	public void unRegister(String cName){
		Function f=this.findFunction(cName);
		if(f!=null) {
			f.destory();
			customFuns.remove(cName);
			aliasMaps.remove(cName);
		}else{
			super.unRegister(cName);
		}
	}
	
	@java.lang.Override
	public Function findFunction(String functionName){
		if(functionName==null) return null;
		Function fun=customFuns.get(functionName);
		if(fun!=null) return fun;
		fun=baseMaps.get(functionName);
		if(fun!=null) return fun;
		fun=findFunction(aliasMaps.get(functionName));
		if(fun!=null) return fun;
		Object obj=this.find(functionName);
		if(obj!=null){
			AdapterFunction af=new AdapterFunction(obj);
			af.setcName(functionName);
			return af;
		}
		return null;
	}
	



	@Override
	public void register(Object object) {
		if(Function.class.isAssignableFrom(object.getClass())){
			Function fun=Function.class.cast(object);
			this.register(fun);
		}else{
			super.register(object);
		}
		
	}


	@Override
	public void register(String name, Object object) {
		if(Function.class.isAssignableFrom(object.getClass())){
			Function fun=Function.class.cast(object);
			this.register(fun);
			if(!name.equals(fun.getName())) this.registerAlias(fun.getName(), fun.getAlias());
		}else{
			super.register(object);
		}
	}
		
}
